test(dogfood): pin that the object-existence gates are WIRED, not just implemented (#4613) - #4615
Merged
Merged
Conversation
…t implemented (#4613) #3770 (data path) and #3867 (analytics cube auto-inference) are both implemented and unit-tested. Neither implementation is what this test protects: it protects the WIRING, which nothing asserted. Measured, not assumed. Deleting the five lines in `service-analytics/src/plugin.ts` that hand `isRegisteredObject` to the service — switching the #3867 gate off in production while leaving the implementation and every unit test untouched — left the whole repo green: service-analytics 299/299, dogfood 395/395. The gate only logs a one-shot stand-down `warn`, which nobody asserts, so `/analytics/query` silently reverts to "any table the connection can see is readable", the exact state #3867 was filed for. Deleting #3770's call site from `findData`, by contrast, reddens four tests immediately. The asymmetry is the test SHAPE, not luck. #3770's suite drives the real `protocol.findData`, so the call site is inside the object under test. #3867's suite injects the probe as config (`new AnalyticsService({ isRegisteredObject })`), so it proves how the service behaves once handed a probe — never that anyone hands it one. Prime Directive #10's closing line in mirror image: a `case` label is not enforcement, check the CALL SITE. This repo has already paid for this exact gap once — `analytics-rls`'s own header records that every pre-existing analytics RLS test injected `getReadScope` into a hand-built service, none booted the real plugin, and "which is how the gap shipped" (#3597). #3867 sits in the identical position, and the pattern is spreading: `measure-source-field-gate.test.ts` is a newer gate wired the same injected way. The new gate goes through `bootStack` (real plugin lifecycle, real Hono app, real HTTP) and never constructs a service by hand. Verified to bite: with this test in place, experiment A reddens 3 cases and experiment B reddens 1. Probe target is `sqlite_master`, not an invented name: the harness boots `sqlite-wasm`, so it is guaranteed to exist and hold rows while never being a registered object. That is the case that actually regressed — #3867's live repro read real rows out of it — and it keeps the gate honest, since a 404 here cannot be explained away by "there was no table anyway", the loophole the pre-#3770 driver-error-string 404 depended on. Also asserted: a premise check that the table IS readable straight through the engine (ground truth, and it pins #3770's choice to gate at the protocol ingress rather than the engine, so internal callers keep working), and controls proving a registered object still serves on both surfaces — without which a simply-broken boot would make every 404 above pass for the wrong reason. Test-only; releases nothing (empty changeset). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWHv5StvA4KDkHhx19xufX
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckNo hand-written docs reference the 0 changed package(s). ✅ |
os-zhuang
marked this pull request as ready for review
August 2, 2026 11:12
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #4613. Test-only — no runtime change.
The gap, measured
#3770 (data path) and #3867 (analytics cube auto-inference) are both implemented and unit-tested. Neither implementation is what this protects. It protects the wiring, which nothing asserted.
Two deletion experiments, each removing only the lines that hand the probe to the service — implementation and unit tests untouched:
service-analytics/src/plugin.tspassingisRegisteredObjectthis.assertObjectRegistered(request.object)infindDataExperiment A means the #3867 gate could be deleted from production by one refactor and nothing in the repo would notice. It only logs a one-shot stand-down
warnthat nobody asserts, so/analytics/querysilently reverts to "any table the connection can see is readable" — the exact state #3867 was filed for.Why the asymmetry — it's the test shape, not luck
protocol.findData. The call site is inside the object under test → deleting it reddens.new AnalyticsService({ isRegisteredObject }). It proves how the service behaves once handed a probe — never that anyone hands it one.Prime Directive #10's closing line in mirror image: a
caselabel is not enforcement, check the CALL SITE. (#3106 was the same lesson pointing the other way.)This repo has already paid for this exact gap once. From
analytics-rls.dogfood.test.ts's own header, verbatim:That was #3597. #3867 sits in the identical position, and the pattern is spreading —
measure-source-field-gate.test.tsis a newer gate wired the same injected way.Verified to bite
With this test in place, the same two experiments now redden:
Why
sqlite_masterand not an invented nameThe harness boots
sqlite-wasm, sosqlite_masteris guaranteed to exist and hold rows while never being a registered object. That is the case that actually regressed — #3867's live repro read real rows out of it ({index: 262, table: 71, view: 1}) — and it keeps the gate honest: a 404 here cannot be explained away by "there was no table anyway", which is precisely the loophole the pre-#3770 driver-error-string 404 depended on.What's asserted
Everything goes through
bootStack(real plugin lifecycle, real Hono app, real HTTP) and never constructs a service by hand.GET /data/sqlite_master→ 404OBJECT_NOT_FOUND(SCREAMING_SNAKE per ADR-0112); the write verb too.POST /analytics/queryscalar and grouped, plus/analytics/sql, all 404, with the response asserted not to carry"rows"orFROM "sqlite_master"./data, and still auto-infers a cube on/analytics/query(theobject-metricKPI path analytics /query 未做 cube 存在性校验,未注册名直达驱动当表名;且错误路径原样回显驱动 SQL(#3770 同类,另一子系统) #3867 narrowed but must not have removed). Without these, a simply-broken boot would make every 404 above pass for the wrong reason.pnpm testgreen across the monorepo (132/132 turbo tasks).Empty changeset — the CI check explicitly allows one for changes that release nothing.
🤖 Generated with Claude Code
https://claude.ai/code/session_01EWHv5StvA4KDkHhx19xufX
Generated by Claude Code